using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Windows.Forms;
using System.Globalization;
using System.Reflection;
using System.IO;

namespace needle.UI.Controls.Flat.Utilities.Drawing
{
	public class DrawHelpers
	{
		protected static SizeConverter msc = new SizeConverter();

		protected static PointConverter mpc = new PointConverter();

		protected static Type mstringType = Type.GetType("System.String");
		
		#region Constructors
		
		private DrawHelpers()
		{
		}

		#endregion

		#region Internal helpers

		private static GraphicsPath GetCapsule(RectangleF baseRect)
		{
			Single diameter;
			RectangleF arcRect;
			GraphicsPath rr = new GraphicsPath();
			try
			{
				if (baseRect.Width > baseRect.Height)
				{
					diameter = baseRect.Height;
					arcRect = new RectangleF(baseRect.Location, new 
						SizeF(diameter, diameter));
					rr.AddArc(arcRect, 90, 180);
					arcRect.X = baseRect.Right - diameter;
					rr.AddArc(arcRect, 270, 180);
				}
				else if (baseRect.Height > baseRect.Width)
				{
					diameter = baseRect.Width;
					arcRect = new RectangleF(baseRect.Location, new
						SizeF(diameter, diameter));
					rr.AddArc(arcRect, 180, 180);
					arcRect.Y = baseRect.Bottom - diameter;
					rr.AddArc(arcRect, 0, 180);
				}
				else
				{
					rr.AddEllipse(baseRect);
				}
			}
			catch
			{
				rr.AddEllipse(baseRect);
			}
			finally
			{
				rr.CloseFigure();
			}

			return rr;
		}

		#endregion

		#region Methods

		public static string SizeToString(Size size)
		{
			return (string)msc.ConvertTo(null, CultureInfo.CurrentCulture,  size, mstringType);
		}

		public static Size StringToSize(string str)
		{
			return (Size)msc.ConvertFrom(null, CultureInfo.CurrentCulture,str);
		}

		public static string PointToString(Point point)
		{
			return (string)mpc.ConvertTo(null, CultureInfo.CurrentCulture,point, mstringType);
		}

		public static Point StringToPoint(string str)
		{
			return (Point)mpc.ConvertFrom(null, CultureInfo.CurrentCulture,str);
		}

		public static GraphicsPath GetRoundedRect(RectangleF baseRect, Single radius)
		{
			if (radius <= 0) 
			{
				GraphicsPath p = new GraphicsPath();
				p.AddRectangle(baseRect);
				return p;
			}

			if (radius >= (Math.Min(baseRect.Width, baseRect.Height) / 2.0))
				return GetCapsule(baseRect);

			Single diameter = radius + radius;
			RectangleF arcRect = new RectangleF(baseRect.Location, new SizeF(diameter,diameter));
			
			GraphicsPath rr	= new GraphicsPath();
			rr.AddArc(arcRect, 180, 90);

			arcRect.X = baseRect.Right - diameter;
			rr.AddArc(arcRect, 270, 90);

			arcRect.Y = baseRect.Bottom - diameter;
			rr.AddArc(arcRect, 0, 90);

			arcRect.X = baseRect.Left;
			rr.AddArc(arcRect, 90, 90);

			rr.CloseFigure();	
		
			return rr;
		}

		public static void Draw3DRect(Graphics g, Rectangle rc, Color topLeft, Color bottomRight)
		{
			Draw3DRect(g, rc.Left, rc.Top, rc.Width, rc.Height,  topLeft, bottomRight);
		}

		public static void Draw3DRect(Graphics g, int x, int y, int width, int height, Color topLeft, Color bottomRight)
		{
			using (Brush brushTopLeft = new SolidBrush(topLeft),
					   brushBottomRight = new SolidBrush(bottomRight))
			{
				g.FillRectangle(brushTopLeft, x, y, width - 1, 1);
				g.FillRectangle(brushTopLeft, x, y, 1, height - 1);
				g.FillRectangle(brushBottomRight, x + width, y, -1, height);
				g.FillRectangle(brushBottomRight, x, y + height, width, -1);
			}
		}

		public static void DrawRectangleWithExternBound(Graphics g, Pen p, Rectangle r)
		{
			if (p.Width > 0.0)
			{
				r.Y += (int)p.Width-1;
				r.X += (int)p.Width-1;
				r.Width -= (int)(p.Width*2-1);
				r.Height -= (int)(p.Width*2-1);
				g.DrawRectangle(p,r);
			}
		}

		public static Bitmap LoadBitmap(Type assemblyType, string imageName)
		{
			return LoadBitmap(assemblyType, imageName, false, new Point(0,0));
		}

		public static Bitmap LoadBitmap(Type assemblyType, string imageName, Point transparentPixel)
		{
			return LoadBitmap(assemblyType, imageName, true, transparentPixel);
		}

		protected static Bitmap LoadBitmap(Type assemblyType, 
			string imageName, 
			bool makeTransparent, 
			Point transparentPixel)
		{
			Assembly myAssembly = Assembly.GetAssembly(assemblyType);
			Stream imageStream = myAssembly.GetManifestResourceStream(imageName);

			Bitmap image = new Bitmap(imageStream);
			if (makeTransparent)
			{
				Color backColor = image.GetPixel(transparentPixel.X, transparentPixel.Y);
				image.MakeTransparent(backColor);
			}
			    
			return image;
		}

		public static ImageList LoadBitmapStrip(Type assemblyType, string imageName, Size imageSize)
		{
			return LoadBitmapStrip(assemblyType, imageName, imageSize, false, new Point(0,0));
		}
		
		public static ImageList LoadBitmapStrip(Type assemblyType, 
			string imageName, 
			Size imageSize,
			Point transparentPixel)
		{
			return LoadBitmapStrip(assemblyType, imageName, imageSize, true, transparentPixel);
		}

		protected static ImageList LoadBitmapStrip(Type assemblyType, 
			string imageName, 
			Size imageSize,
			bool makeTransparent,
			Point transparentPixel)
		{
			ImageList images = new ImageList();

			images.ImageSize = imageSize;

			Assembly myAssembly = Assembly.GetAssembly(assemblyType);

			Stream imageStream = myAssembly.GetManifestResourceStream(imageName);

			Bitmap pics = new Bitmap(imageStream);

			if (makeTransparent)
			{
				Color backColor = pics.GetPixel(transparentPixel.X, transparentPixel.Y);
				pics.MakeTransparent(backColor);
			}
			    
			images.Images.AddStrip(pics);
			return images;
		}

		public static Cursor LoadCursor(Type assemblyType, string cursorName)
		{
			Assembly myAssembly = Assembly.GetAssembly(assemblyType);

			Stream iconStream = myAssembly.GetManifestResourceStream(cursorName);

			return new Cursor(iconStream);
		}

		public static void DrawIcon(Graphics g,Icon icon,Rectangle drawRect,bool grayed,bool pushed)
		{
			if(g == null || icon == null)
			{
				return;
			}

			if(pushed)
			{
				drawRect.Location = new Point(drawRect.X + 1,drawRect.Y + 1);
			}

			if(grayed)
			{
				Size s = new Size(drawRect.Size.Width-1,drawRect.Size.Height-1);
				ControlPaint.DrawImageDisabled(g,new Bitmap(icon.ToBitmap(),s),drawRect.X,drawRect.Y,Color.Transparent);
			}
			else
			{
				g.DrawIcon(icon,drawRect);
			}
		}

		public static void DrawImage(Graphics g,Image image,Rectangle drawRect,bool grayed,bool pushed)
		{
			if(g == null || image == null)
			{
				return;
			}

			if(pushed)
			{
				drawRect.Location = new Point(drawRect.X + 1,drawRect.Y + 1);
			}

			if(grayed)
			{
				Size s = new Size(drawRect.Size.Width-1,drawRect.Size.Height-1);
				ControlPaint.DrawImageDisabled(g,new Bitmap(image,s),drawRect.X,drawRect.Y,Color.Transparent);
			}
			else
			{
				g.DrawImage(image,drawRect);
			}
		}

		#endregion
	}
}
